FIRLPF   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 69
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 32
dl 0
loc 69
rs 10
c 0
b 0
f 0
wmc 9

4 Functions

Rating   Name   Duplication   Size   Complexity  
A reset 0 3 1
A initZ_ 0 11 2
A filter 0 11 2
A constructor 0 22 4
1
/*
2
 * Copyright (c) 2019 Rafael da Silva Rocha.
3
 * Copyright (c) 2014 Florian Markert
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining
6
 * a copy of this software and associated documentation files (the
7
 * "Software"), to deal in the Software without restriction, including
8
 * without limitation the rights to use, copy, modify, merge, publish,
9
 * distribute, sublicense, and/or sell copies of the Software, and to
10
 * permit persons to whom the Software is furnished to do so, subject to
11
 * the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 *
24
 */
25
26
/**
27
 * @fileoverview FIR LPF. Based on the FIR LPF from Fili by Florian Markert.
28
 * @see https://github.com/rochars/wavefile
29
 * @see https://github.com/markert/fili.js
30
 */
31
32
/**
33
 * A FIR low pass filter.
34
 */
35
export class FIRLPF {
36
  
37
  /**
38
   * @param {number} order The order of the filter.
39
   * @param {number} sampleRate The sample rate.
40
   * @param {number} cutOff The cut off frequency.
41
   */
42
  constructor(order, sampleRate, cutOff) {
43
    /** @type {number} */
44
    let omega = 2 * Math.PI * cutOff / sampleRate;
45
    /** @type {number} */
46
    let dc = 0;
47
    this.filters = [];
48
    for (let i = 0; i <= order; i++) {
49
      if (i - order / 2 === 0) {
50
        this.filters[i] = omega;
51
      } else {
52
        this.filters[i] = Math.sin(omega * (i - order / 2)) / (i - order / 2);
53
        // Hamming window
54
        this.filters[i] *= (0.54 - 0.46 * Math.cos(2 * Math.PI * i / order));
55
      }
56
      dc = dc + this.filters[i];
57
    }
58
    // normalize
59
    for (let i = 0; i <= order; i++) {
60
      this.filters[i] /= dc;
61
    }
62
    this.z = this.initZ_();
63
  }
64
65
  /**
66
   * @param {number} sample A sample of a sequence.
67
   * @return {number}
68
   */
69
  filter(sample) {
70
    this.z.buf[this.z.pointer] = sample;
71
    /** @type {number} */
72
    let out = 0;
73
    for (let i = 0, len = this.z.buf.length; i < len; i++) {
74
      out += (
75
        this.filters[i] * this.z.buf[(this.z.pointer + i) % this.z.buf.length]);
76
    }
77
    this.z.pointer = (this.z.pointer + 1) % (this.z.buf.length);
78
    return out;
79
  }
80
81
  /**
82
   * Reset the filter.
83
   */
84
  reset() {
85
    this.z = this.initZ_();
86
  }
87
88
  /**
89
   * Return the default value for z.
90
   * @private
91
   */
92
  initZ_() {
93
    /** @type {!Array} */
94
    let r = [];
95
    for (let i = 0; i < this.filters.length - 1; i++) {
96
      r.push(0);
97
    }
98
    return {
99
      buf: r,
100
      pointer: 0
101
    };
102
  }
103
}
104